
package Nonogram;

/**
 * Solver
 * @author Rachel Wedewer, Mollie Burkle, Kristen Nielsen
 * Date Modified: 4/30/2014
 * 
 * This is one of four of the main components of Nonogram. MKR Nonogram is a rule-based system, and this class acts as the
 * intelligence of the system.  It processes "rules" (mostly if statements) until it is able to mark an unknown cell(-1)
 * either filled(1) or blank(0). The system first processes through the row clues and when no more moves are found, it
 * moves on to process the column clues with similar rules used on the rows to look for another move.
 * 
 * When the runSolver() method is executed it will look for errors, then one move, complete that move, and send a
 * message back to the GUI.  When runSolverAsLongAsPossible() method is executed it will call runSolver() until 
 * the puzzle is solved, or the runSolver() method is unable to find another move.  After marking a cell a different state the GUI 
 * is updated and also the solver accesses the Message class for a string value related to the move to display through the GUI.
 * 
 * 
 * DEFINITIONS
 * EMPTY (-1):  an unknown cell
 * BLANK  (0):   a white cell
 * FILLED (1):  a black cell
 * BLOCK:       a cluster of filled cells/boxes
 */
public class Solver {

    Nonogram controller;
    GridArray puzzleGrid;
    CluesArray rowCluesArray;
    CluesArray colCluesArray;
    ErrorDetection errorD;
    Boolean runningSolver;
    Messages msg;

    int size;
    int[] rowClues;
    int[] colClues;
    int[] unsolvedRows;
    int[] unsolvedCols;

    public Solver(Nonogram controller, Data data) {
        this.controller = controller;
        this.puzzleGrid = data.getGrid();
        this.rowCluesArray = data.getRows();
        this.colCluesArray = data.getCols();
        this.size = data.getBoardsize();
        this.errorD = new ErrorDetection(controller, data);
        unsolvedRows = new int[size];
        unsolvedCols = new int[size];
        this.msg = new Messages(this.controller);

    }

        public void runSolver() {
            boolean errors = checkForErrorsBeforeRunning();
            if (errors){
            	runningSolver=false;
                return;
            } 
            
            /*
             *  ||||||||||||||||||||||||||||||||||
             * 	|||||||||||||| ROWS ||||||||||||||
             *  ||||||||||||||||||||||||||||||||||
             */
            
            for (int row = 0; row < size; row++) {
            	if (puzzleGrid.allCellsInRowMarked(row)){
                	//skip Row
                	//do nothing and move onto next line
                }
            	else{
            	rowClues = rowCluesArray.getLineClues(row);

            	
                if (puzzleGrid.getNumberFillState(true, 0, row) > 1) {
                    int firstBlankCell =  puzzleGrid.getFirstCellState(true, 0, row, 0);
                    int secondBlankCell = puzzleGrid.getFirstCellState(true, 0, row, firstBlankCell+1);
                    if (secondBlankCell - firstBlankCell == 1) {
                            int count = 2;
                            while (count < puzzleGrid.getNumberFillState(true, 0, row)) {
                                    secondBlankCell = puzzleGrid.getFirstCellState(true, 0, row, secondBlankCell+1);
                                    count += 1;
                            }
                    }
                    if (secondBlankCell != -1 && secondBlankCell - firstBlankCell < rowClues[0]) {
                            for (int col = firstBlankCell; col < secondBlankCell; col++) {
                                    if (puzzleGrid.getCellValue(row, col) == -1) {
                                            puzzleGrid.setCellBlankState(row, col);
                                            msg.markBetweenAlreadyMarked(row, col, false, true, true);
                                            return;
                                    }
                            }
                    }
                }                
                
                if (rowClues.length == 1) {
                    
                    if (rowClues[0] > Math.round(size/2)) {
                        int overlapIndex = LineSolver(puzzleGrid.getRow(row), rowClues, 0, size);
                        if (overlapIndex >= 0) {
                            puzzleGrid.setCellFillState(row, overlapIndex);
                            msg.singleClueOverlap(true, row, overlapIndex, overlapIndex);
                            return;
                        }
                    }
                    if (puzzleGrid.getNumberFillState(true, 1, row) == rowClues[0]) {
                        for (int col = 0; col < size; col++) { // look for nearest empty cell in line
                            if (puzzleGrid.getCellValue(row, col) == -1) {
                                puzzleGrid.setCellBlankState(row, col);
                                msg.singleClueComplete(true, row, col, rowClues[0]);
                                return;
                            }
                        }
                    }
                    if (puzzleGrid.getNumberFillState(true, 1, row) > 0) {
                        int difference = rowClues[0] - puzzleGrid.getNumberFillState(true, 1, row);
                        int firstFilledCell = puzzleGrid.getFirstCellState(true, 1, row, 0);
                        int endOfFill = firstFilledCell + puzzleGrid.getNumberFillState(true, 1, row);
                        for (int col = 0; col < firstFilledCell - difference; col++) {
                            if (puzzleGrid.getCellValue(row, col) == -1) {
                                puzzleGrid.setCellBlankState(row, col);
                                msg.wiggleRoom(row, col, firstFilledCell, true);
                                return;
                                }
                        }
                        for (int col = endOfFill + difference; col < size; col++) {
                                if (puzzleGrid.getCellValue(row, col) == -1) {
                                        puzzleGrid.setCellBlankState(row, col);
                                        msg.wiggleRoom(row, col, endOfFill+difference, true);
                                        return;
                                }
                        }
                    }
                        if (puzzleGrid.getNumberFillState(true, 1, row) > 1) {
                                int firstFilledCell = puzzleGrid.getFirstCellState(true, 1, row, 0);
                                int secondFilledCell = puzzleGrid.getFirstCellState(true, 1, row, firstFilledCell+1);
                                if (secondFilledCell - firstFilledCell == 1) {
                                        int count = 2;
                                        while (count < puzzleGrid.getNumberFillState(true, 1, row)) {
                                                secondFilledCell = puzzleGrid.getFirstCellState(true, 1, row, secondFilledCell+1);
                                                count += 1;
                                        }
                                        if (secondFilledCell != -1 && secondFilledCell - firstFilledCell + 1 <= rowClues[0]) {
                                                for (int col = firstFilledCell; col < secondFilledCell; col++) {
                                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                                                puzzleGrid.setCellFillState(row, col);
                                                                msg.markBetweenAlreadyMarked(row, col, true, true, true);
                                                                return;
                                                        }
                                                }
                                        }
                                }
                        }
                    if (puzzleGrid.getNumberFillState(true, 0, row) == (size - rowClues[0])) {
                        for (int col = 0; col < size; col++) {
                            if (puzzleGrid.getCellValue(row, col) == -1) {
                                puzzleGrid.setCellFillState(row, col);
                                msg.multiClueAllFilledIn(row, col, true, true);
                                return;
                            }
                        }
                   
                    }
                    if (puzzleGrid.getNumberFillState(true, 0, row) > 0) {
                        int firstBlankCell = puzzleGrid.getFirstCellState(true, 0, row, 0);
                        if (firstBlankCell > 0 && firstBlankCell + 1 < rowClues[0]) {
                                for (int col = 0; col < firstBlankCell; col++) {
                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                                puzzleGrid.setCellBlankState(row, col);
                                                msg.markBetweenAlreadyMarked(row, col, false, true, false);
                                                return;
                                        }
                                }
                        }
                        
                       
                        if (rowClues[0] > ((size - puzzleGrid.getNumberFillState(true, 0, row)) / 2)) {
                            int startOfEmpty = puzzleGrid.getFirstCellState(true, -1, row, 0);
                            int space = size - puzzleGrid.getNumberFillState(true, 0, row);
                            if (startOfEmpty >= 0) {
                                int overlapIndex = LineSolver(puzzleGrid.getRow(row), rowClues, startOfEmpty, space);
                                if (overlapIndex >= 0) {
                                    puzzleGrid.setCellFillState(row, overlapIndex);
                                    msg.overlapInRemainingSpace(row, overlapIndex, true, space);
                                    return;
                                }
                            }
                        }
                    }
                } else {
                	
                	if (rowClues.length > 1) {
                		
                    	// Rows whose clues sum up to equal the board length, fill in designated positions
                        if (sumClues(rowClues) + rowClues.length - 1 == size) {
                        	int[] cluesCopy = new int[rowClues.length];
                        	int pointer = 0;
                        	for (int i = 0; i < rowClues.length; i++) {
                        		cluesCopy[i] = rowClues[i];
                        	}
                        	for (int j = 0; j < size; j++) {
                        		if (cluesCopy[pointer] == 0) {
                        			if (puzzleGrid.getCellValue(row, j) == -1) {
                        				puzzleGrid.setCellBlankState(row, j);
                        				msg.sumClueBlockComplete(true, row, j, pointer);
                         		 		return;
                        			}
                        			else {
                        				cluesCopy[pointer]-= 1;
                        				pointer++;
                        			}
                        		}
                        		if (cluesCopy[pointer] > 0) {
                        			if (puzzleGrid.getCellValue(row, j) == -1) {
                        				puzzleGrid.setCellFillState(row, j);
                         		 		msg.sumEqualsLineLength(true, row, j, pointer);
                         		 		return;
                        			}
                        			else if (puzzleGrid.getCellValue(row, j) == 1){
                        				cluesCopy[pointer]-= 1;
                        			}
                        		}
                        	}
                        }
                    }
                	
                    if (lineComplete(puzzleGrid.getRow(row), rowClues)) {
                        for (int col = 0; col < size; col++) {
                                if (puzzleGrid.getCellValue(row, col) == -1) {
                                        puzzleGrid.setCellBlankState(row, col);
                                        msg.multiClueAllFilledIn(row, col, false, true);
                                        return;
                                }
                        }
                    }
                    if (puzzleGrid.getNumberFillState(true, 0, row) == (size - sumClues(rowClues))) {
                        for (int col = 0; col < size; col++) {
                                if (puzzleGrid.getCellValue(row, col) == -1) {
                                        puzzleGrid.setCellFillState(row, col);
                                        msg.multiClueAllFilledIn(row, col, true, true);
                                        return;
                                }
                        }
                    }

                    if (puzzleGrid.getCellValue(row, 0) == 0) {
                        int numberOfBlanks = puzzleGrid.getNumberFillState(true, 0, row);
                        int firstRun = 0;
                        int secondRun = 0;
                        int cell = 0;
                        while (puzzleGrid.getCellValue(row, cell) == 0) {
                            firstRun += 1;
                            cell += 1;
                        }
                        if (numberOfBlanks != firstRun) {
                            cell = size - 1;
                            while (puzzleGrid.getCellValue(row, cell) == 0) {
                                secondRun += 1;
                                cell -= 1;
                            }
                        }
                        if ((numberOfBlanks == (firstRun + secondRun)) && ((size - numberOfBlanks) == (sumClues(rowClues) + rowClues.length - 1))) {
                            int index = 0;
                            int run = 0;
                            for (int col = firstRun; col < size - secondRun; col++) {
                                if (puzzleGrid.getCellValue(row, col) == 1) {
                                    run += 1;
                                }
                                else if (puzzleGrid.getCellValue(row, col) == 0) {
                                    run = 0;
                                    index += 1;
                                }
                                else {
                                    if (run == rowClues[index]) {
                                        run = 0;
                                        index += 1;
                                        puzzleGrid.setCellBlankState(row, col);
                                        msg.multiClueRemainingLineLengthEqualsClueSum(row, col, 0, true, size - numberOfBlanks);
                                        return;
                                    }
                                    else {
                                        run += 1;
                                        puzzleGrid.setCellFillState(row, col);
                                        msg.multiClueRemainingLineLengthEqualsClueSum(row, col, 1, true, size - numberOfBlanks);
                                        return;
                                    }
                                }
                            }
                        }
                    }
                    if (puzzleGrid.getCellValue(row, 0) == 1) {
                        int run = 0;
                        int cell = 0;
                        while (puzzleGrid.getCellValue(row, cell) == 1) {
                            run += 1;
                            cell += 1;
                        }
                        if (run == rowClues[0]) {
                            if (puzzleGrid.getCellValue(row, run) == -1) {
                                puzzleGrid.setCellBlankState(row, run);
                                msg.multiClueFirstClueComplete(row, run, true);
                                return;
                            }
                        }
                    }
                    if (puzzleGrid.getCellValue(row, size - 1) == 1) {
                        int run = 0;
                        int cell = size - 1;
                        while (puzzleGrid.getCellValue(row, cell) == 1) {
                            run += 1;
                            cell -= 1;
                        }
                        if (run == rowClues[rowClues.length - 1]) {
                            if (puzzleGrid.getCellValue(row, size - run - 1) == -1) {
                                puzzleGrid.setCellBlankState(row, (size - run - 1));
                                msg.multiClueLastClueComplete(row, size-run-1, true);
                                return;
                            }
                        }
                    }
                    int firstCellMarked = puzzleGrid.getFirstCellState(true, 1, row, 0);
                    if (firstCellMarked >= 0) {
                        int blankSpace = 0;
                        int cell = 0;
                        while (puzzleGrid.getCellValue(row, cell) != 1) {
                            if (puzzleGrid.getCellValue(row, cell) == -1) {
                                blankSpace += 1;
                            }
                            cell += 1;
                        }
                        if ((rowClues[0] > 1 && blankSpace < rowClues[0]) || 
                                (rowClues.length == 2 && rowClues[0] != rowClues[1] && blankSpace <= rowClues[0])) {
                            int run = 0;
                            cell = firstCellMarked;
                            while (puzzleGrid.getCellValue(row, cell) == 1) {
                                run += 1;
                                cell += 1;
                            }
                            if (run == rowClues[0]) {
                                for (int col = 0; col < firstCellMarked; col++) {
                                    if (puzzleGrid.getCellValue(row, col) == -1) {
                                        puzzleGrid.setCellBlankState(row, col);
                                        msg.multiClueFirstClueComplete(row, col, true);
                                        return;
                                    }
                                }
                                if (puzzleGrid.getCellValue(row, firstCellMarked + run) == -1) {
                                    puzzleGrid.setCellBlankState(row, firstCellMarked + run);
                                    msg.multiClueFirstClueComplete(row, firstCellMarked+run, true);
                                    return;
                                }
                            }
                        }
                    }
                    int lastCellMarked = puzzleGrid.getLastCellState(true, 1, row, size - 1);
                    if (lastCellMarked > 0) {
                        int blankSpace = 0;
                        int cell = size - 1;
                        while (puzzleGrid.getCellValue(row, cell) != 1) {
                            if (puzzleGrid.getCellValue(row, cell) == -1) {
                                blankSpace += 1;
                            }
                            cell -= 1;
                        }
                        if ((rowClues[rowClues.length - 1] > 1 && blankSpace < rowClues[rowClues.length - 1]) || 
                                (rowClues.length == 2 && rowClues[0] != rowClues[1] && blankSpace <= rowClues[rowClues.length -1])) {
                            int run = 0;
                            cell = lastCellMarked;
                            while (puzzleGrid.getCellValue(row, cell) == 1) {
                                run += 1;
                                cell -= 1;
                            }
                            if (run == rowClues[rowClues.length - 1]) {
                                for (int col = lastCellMarked + 1; col < size; col++) {
                                    if (puzzleGrid.getCellValue(row, col) == -1) {
                                        puzzleGrid.setCellBlankState(row, col);
                                        msg.multiClueLastClueComplete(row, col, true);
                                        return;
                                    }
                                }
                                if (puzzleGrid.getCellValue(row, lastCellMarked - run) == -1) {
                                    puzzleGrid.setCellBlankState(row, lastCellMarked - run);
                                    msg.multiClueLastClueComplete(row, lastCellMarked-run, true);
                                    return;
                                }
                            }
                        }
                    }
                }
                

                //EDGE RELATED CLUES Sorry its long  
                //Edges Filling
	                if (rowClues[0]!=1){
	                    Boolean foundGivenCell = false;
	                    int pointerPush = 0;
		                    while (true){
		                    	if (puzzleGrid.getCellValue(row, pointerPush)==0){
		                    		pointerPush=pointerPush+1;
		                    	}
		                    	else{break;}
		                    	if(pointerPush==size-1){
		                    		break;
		                    	}
		                    }
		                for(int col = pointerPush; col < rowClues[0]+pointerPush; col++){
		                	if (foundGivenCell && puzzleGrid.getCellValue(row, col) == -1){
		                		puzzleGrid.setCellFillState(row, col);
		                		msg.firstRowClueEdgeMessage(row, col, pointerPush, rowClues[0]);
		                		return;
		                	}
		                	else if (puzzleGrid.getCellValue(row, col) == 1){
		                		foundGivenCell = true;
		                	}
		                	if (col==size-1){
		                		break;
		                	}
		                }
	                }
	                if(rowClues[rowClues.length-1] != 1){
		                Boolean foundGivenCell = false;
		                int pointerPush = size-1;
		                	while(true){
		                		if (puzzleGrid.getCellValue(row, pointerPush)== 0){
			                		pointerPush = pointerPush-1;
			                	}
			                	else{
			                		break;}
			                	if(pointerPush==0){break;}
		                	}
		                for(int col = pointerPush; col > ((pointerPush) - rowClues[rowClues.length-1]); col--){
		                	if (foundGivenCell && puzzleGrid.getCellValue(row, col) == -1){
		                		puzzleGrid.setCellFillState(row, col);
		                		msg.LastRowClueEdgeMessage(row, col, size-1 -pointerPush, rowClues[rowClues.length-1]);
		                		return;
		                	}
		                	else if (puzzleGrid.getCellValue(row, col) == 1){
		                		foundGivenCell = true;
		                	}
		                	if (col==0){
		                		break;
		                	}
	                	}
	                }
	              //Edges Blanking
	              if(rowClues[0]!=1){
	              Boolean foundGivenCell = false;
	              for(int col = rowClues[0]-1; col > -1; col--){
	            	  if (foundGivenCell && puzzleGrid.getCellValue(row, col) == -1){
	                		puzzleGrid.setCellBlankState(row, col);
	                		msg.firstRowClueEdgeBlankMessage(row, col, rowClues[0]);
	                		return;
	                	}
	                	else if (puzzleGrid.getCellValue(row, col) == 0){
	                		foundGivenCell = true;
	                	}
	              	}
	              }
	              if(rowClues[rowClues.length-1] != 1){
	              Boolean foundGivenCell = false;
	              for(int col = ((size) - rowClues[rowClues.length-1]); col < size; col++){
	            	  if (foundGivenCell && puzzleGrid.getCellValue(row, col) == -1){
	                		puzzleGrid.setCellBlankState(row, col);
	                		msg.LastRowClueEdgeBlankMessage(row, col, rowClues[rowClues.length-1]);
	                		return;
	                	}
	                	else if (puzzleGrid.getCellValue(row, col) == 0){
	                		foundGivenCell = true;
	                	}
	              }
	              }
	              
	  
          //Overlap first clue Possibles
            if (rowClues[0] != 1 && rowClues[0] !=0){
            	int end =((size-1)-(sumClues(rowClues))+(rowClues[0])-(rowClues.length-1));
            	int start = end-rowClues[0]+1;
            	
            	for(int overlapPointer = 0; overlapPointer < rowClues[0]; overlapPointer++){
            		if(overlapPointer <=end && overlapPointer>=start){
            			if (puzzleGrid.getCellValue(row, overlapPointer)== -1){
            				puzzleGrid.setCellFillState(row, overlapPointer);
                    		msg.overlapFirstRowClueMC(row, overlapPointer);
                    		return;
            			}
            		}
            	}
            }
            //Overlap last clue Possibles
            if (rowClues[rowClues.length-1] != 1 && rowClues[0] !=0){
            	int start = (sumClues(rowClues)-rowClues[rowClues.length-1])+rowClues.length-1;
            	int end = start + rowClues[rowClues.length-1]-1;
            	for(int overlapPointer = ((size-1)- rowClues[rowClues.length-1])+1; overlapPointer < size; overlapPointer++){
            		if(overlapPointer <=end && overlapPointer>=start){
            			if (puzzleGrid.getCellValue(row, overlapPointer)== -1){
            				puzzleGrid.setCellFillState(row, overlapPointer);
                    		msg.overlapLastRowClueMC(row,	overlapPointer);
                    		return;
            			}
            		}
            	}
            }
	              
    	  ////////
    	  //Process the line Forward
    	  ///////
              while(true){
            	  int col = 0;
            	  int cluePointer = 0;
            	  int clueValueRemaining = rowClues[cluePointer];
            	  
            	  while(col<size -1){
            		  
            		  if(puzzleGrid.getCellValue(row, col) == 1){
            			  if (clueValueRemaining == 1 && col != size -1){
            				  if (puzzleGrid.getCellValue(row, col+1) == -1){
            				   puzzleGrid.setCellBlankState(row, col+1);
            				   msg.processFromFrontRowBlank(row, col, cluePointer, rowClues[cluePointer]);
            				   return;}
            			  }
            			  else{
            				  while(clueValueRemaining!=0 && col != size -1){
            					  clueValueRemaining = clueValueRemaining-1;
            					  
            					  if (puzzleGrid.getCellValue(row, col+1) == -1){
            						  //Value remaining fill
            						  if (clueValueRemaining >0 ){
            							  puzzleGrid.setCellFillState(row, col+1);
            							  msg.processFromFrontRowFill(row, col, cluePointer, rowClues[cluePointer]);
            	        				  return;
            						  }
            						//Blank outspace space blank
            						  else if (clueValueRemaining == 0){
            							  puzzleGrid.setCellBlankState(row, col+1);
            							  msg.processFromFrontRowBlank(row, col, cluePointer, rowClues[cluePointer]);
            	        				  return;
            						  }
            						  
            						  
            					  }
            					  
            					  col = col +1;
            				  }
            			  }
            			  cluePointer = cluePointer +1;
            			  if(cluePointer == rowClues.length){
            				  break;
            			  }
            			  clueValueRemaining = rowClues[cluePointer];
            			  
            		  }
            		  
            		  if(puzzleGrid.getCellValue(row, col) == -1){
            			  break;
            		  }

            		  col = col +1;
            	  }
            	  break;
              }           
	  ////////
	  //Process the line Backwards
	  ///////
          while(true){
        	  int col = size -1;
        	  int cluePointer = rowClues.length-1;
        	  int clueValueRemaining = rowClues[cluePointer];
        	  
        	  while(col>0){
        		  
        		  if(puzzleGrid.getCellValue(row, col) == 1){
        			  if (clueValueRemaining == 1){
        				  if (puzzleGrid.getCellValue(row, col-1) == -1){
        				   puzzleGrid.setCellBlankState(row, col-1);
        				   msg.processFromBackRowBlank(row, col, cluePointer, rowClues.length-1, rowClues[cluePointer]);
        				   return;}
        			  }
        			  else{
        				  while(clueValueRemaining!=0 && col != 0){
        					  clueValueRemaining = clueValueRemaining-1;
        					  
        					  if (puzzleGrid.getCellValue(row, col-1) == -1){
        						  //Value remaining fill
        						  if (clueValueRemaining >0 ){
        							  puzzleGrid.setCellFillState(row, col-1);
        							  msg.processFromBackRowFill(row, col, cluePointer, rowClues.length-1, rowClues[cluePointer]);
        	        				  return;
        						  }
        						  else if (clueValueRemaining == 0){
        							  puzzleGrid.setCellBlankState(row, col-1);
        							  msg.processFromBackRowBlank(row, col, cluePointer, rowClues.length-1, rowClues[cluePointer]);
        	        				  return;
        						  }
        						  
        						  //Blank outspace space blank
        					  }
        					  
        					  col = col -1;
        				  }
        			  }
        			  cluePointer = cluePointer -1;
        			  if(cluePointer == -1){
        				  break;
        			  }
        			  clueValueRemaining = rowClues[cluePointer];
        			  
        		  }
        		  
        		  if(puzzleGrid.getCellValue(row, col) == -1){
        			  break;
        		  }

        		  col = col -1;
        	  }
        	  break;
          }
	              
          


	  ////////
	  //Blank out small gaps
	  ///////
	       if (puzzleGrid.getMinNumClue(rowClues) != 1){       
	    	   int minClue = puzzleGrid.getMinNumClue(rowClues);
	    	   int col = 0;
	    	   int start=0;
	    	   int blankGapRange = 0;
	    	   
	    	   //Start position
	    	   while(col < size){
	    	   
           		if (puzzleGrid.getCellValue(row, col)== -1){
           			start = col;
           			while(puzzleGrid.getCellValue(row, col)== -1){
           				blankGapRange = blankGapRange +1;
           				col = col +1;
           				if (col >= size){
                   			break;}
           				}
           			col = col -1;	
           			}
               	
           		if (blankGapRange > 0){
           			if (blankGapRange < minClue){
           				if (start == 0){
           					
           				}
           				else if (puzzleGrid.getCellValue(row, start-1)== 0){
           					if(start + blankGapRange == size){
           						puzzleGrid.setCellBlankState(row, start);
           						msg.smallGapRow(row, col, minClue);
           						return;
           					}
           					else if (puzzleGrid.getCellValue(row, start+blankGapRange)== 0){
           						puzzleGrid.setCellBlankState(row, start);
           						msg.smallGapRow(row, col, minClue);
           						return;
           					}
           					
           					
           				}
           			}
           			start = col+1;
           			blankGapRange = 0;
           		}
           		
           		col = col + 1;
           		
	    	   	}
	    	   }		
	       		}
            }

            /*
             *  ||||||||||||||||||||||||||||||||||
             * 	|||||||||||| COLUMNS |||||||||||||
             *  ||||||||||||||||||||||||||||||||||
             */
            for(int col = 0; col < size; col++) {
                colClues = colCluesArray.getLineClues(col);
                if (puzzleGrid.allCellsInColMarked(col)){
                	//skip Row
                	//do nothing and move onto next line
                }
                else{
                if(colClues[0] == size) {
                    for(int row = 0; row < size; row++) {       // look for nearest empty cell in line
                        if(puzzleGrid.getCellValue(row, col) == -1) {
                            puzzleGrid.setCellFillState(row, col);
                            // update GUI and return with explanation
                            controller.updateExplanation("Column " + (col +1) + " is a solid fill column" + "\n");
                            return;
                        }
                    }
                }
                else if (colClues[0] == 0) {
                    for (int row = 0; row < size; row++) { //look for nearest empty cell in line
                        if (puzzleGrid.getCellValue(row,col) == -1) {
                            puzzleGrid.setCellBlankState(row, col);
                            controller.updateExplanation("Row " + (row + 1) + ", Col " + (col+1) + " is marked blank because column clue is ZERO\n");
                            return;
                        }
                    }
                }
                if (puzzleGrid.getNumberFillState(false, 0, col) > 1) {
                        int firstBlankCell = puzzleGrid.getFirstCellState(false, 0, col, 0);
                        int secondBlankCell = puzzleGrid.getFirstCellState(false, 0, col, firstBlankCell+1);
                        if (secondBlankCell - firstBlankCell == 1) {
                                int count = 2;
                                while (count < puzzleGrid.getNumberFillState(false, 0, col)) {
                                        secondBlankCell = puzzleGrid.getFirstCellState(false, 0, col, secondBlankCell+1);
                                        count += 1;
                                }
                        }
                        if (secondBlankCell != -1 && secondBlankCell - firstBlankCell < colClues[0]) {
                                for (int row = firstBlankCell; row < secondBlankCell; row++) {
                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                                puzzleGrid.setCellBlankState(row, col);
                                                msg.markBetweenAlreadyMarked(row, col, false, false, true);
                                                return;
                                        }
                                }
                        }
                }
                
                if (colClues.length == 1) {
                        if (colClues[0] > (size/2)) {  
                        	int overlapIndex = LineSolver(puzzleGrid.getCol(col), colClues, 0, size);
                        	if(overlapIndex >= 0) {
                                puzzleGrid.setCellFillState(overlapIndex, col);
                                msg.singleClueOverlap(false, overlapIndex, col, overlapIndex);
                                return;
                        	}
                        }
                        if (puzzleGrid.getNumberFillState(false, 1, col) == colClues[0]) {
                        // number of marked black cells is equal to clue, mark rest blank
                                for (int row = 0; row < size; row++) {
                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                                puzzleGrid.setCellBlankState(row, col);
                                                msg.singleClueComplete(false, row, col, colClues[0]);
                                                return;
                                        }
                                }
                        }
                        if (puzzleGrid.getNumberFillState(false, 0, col) == (size-colClues[0])) {
                                for (int row = 0; row < size; row++) {
                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                                puzzleGrid.setCellFillState(row, col);
                                                msg.multiClueAllFilledIn(row, col, true, false);
                                                return;
                                        }
                                }
               
                        }
                        if (puzzleGrid.getNumberFillState(false, 1, col) > 0) {
                                int difference = colClues[0] - puzzleGrid.getNumberFillState(false, 1, col);
                                int firstFilledCell = puzzleGrid.getFirstCellState(false, 1, col, 0);
                                int endOfFill = firstFilledCell + puzzleGrid.getNumberFillState(false, 1, col);
                                for (int row = 0; row < firstFilledCell - difference; row++) {
                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                                puzzleGrid.setCellBlankState(row, col);
                                                msg.wiggleRoom(row, col, firstFilledCell, false);
                                                return;
                                        }
                                }
                                for (int row = endOfFill + difference; row < size; row ++) {
                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                                puzzleGrid.setCellBlankState(row, col);
                                                msg.wiggleRoom(row, col,endOfFill+difference, false);
                                                return;
                                        }
                                }
                        }
                        if (puzzleGrid.getNumberFillState(false, 1, col) > 1) {
                                int firstFilledCell = puzzleGrid.getFirstCellState(false, 1, col, 0);
                                int secondFilledCell = puzzleGrid.getFirstCellState(false, 1, col, firstFilledCell+1);
                                if (secondFilledCell - firstFilledCell == 1) {
                                        int count = 2;
                                        while (count < puzzleGrid.getNumberFillState(false, 1, col)) {
                                                secondFilledCell = puzzleGrid.getFirstCellState(false, 1, col, secondFilledCell+1);
                                                count += 1;
                                        }
                                }
                                if (secondFilledCell - firstFilledCell + 1 <= colClues[0]) {
                                        for (int row = firstFilledCell; row < secondFilledCell; row++) {
                                                if (puzzleGrid.getCellValue(row, col) == -1) {
                                                        puzzleGrid.setCellFillState(row, col);
                                                        msg.markBetweenAlreadyMarked(row, col, true, false, true);
                                                        return;
                                                }
                                        }
                                }
                        }
                        if (puzzleGrid.getNumberFillState(false, 0, col) > 0) {
                            int firstBlankCell = puzzleGrid.getFirstCellState(false, 0, col, 0);
                            if (firstBlankCell > 0 && firstBlankCell + 1 < colClues[0]) {
                                for (int row = 0; row < firstBlankCell; row++) {
                                    if (puzzleGrid.getCellValue(row, col) == -1) {
                                        puzzleGrid.setCellBlankState(row, col);
                                        msg.markBetweenAlreadyMarked(row, col, false, false, false);
                                        return;
                                    }
                                }
                            }
                            if (colClues[0] > (size - puzzleGrid.getNumberFillState(false, 0, col)) / 2) {
                                int start = puzzleGrid.getFirstCellState(false, -1, col, 0);
                                int space = size - puzzleGrid.getNumberFillState(false, 0, col);
                                if (start >= 0) {
                                    int overlapIndex = LineSolver(puzzleGrid.getCol(col), colClues, start, space);
                                    if (overlapIndex >= 0) {
                                        puzzleGrid.setCellFillState(overlapIndex, col);
                                        msg.overlapInRemainingSpace(overlapIndex, col, false, space);
                                        return;
                                    }
                                }
                            }
                        }
                    }
                    else {
                        if (colClues.length > 1) {
                            if (sumClues(colClues) + colClues.length - 1 == size) {
                                int[] cluesCopy = new int[colClues.length];
                                int pointer = 0;
                                for (int i = 0; i < colClues.length; i++) {
                                    cluesCopy[i] = colClues[i];
                                }
                                for (int j = 0; j < size; j++) {
                                    if (cluesCopy[pointer] == 0) {
                                        if (puzzleGrid.getCellValue(j, col) == -1) {
                                            puzzleGrid.setCellBlankState(j, col);
                                            msg.sumClueBlockComplete(false, j, col, pointer);
                                            return;
                                        } else {
                                            cluesCopy[pointer] -= 1;
                                            pointer++;
                                        }
                                    }
                                    if (cluesCopy[pointer] > 0) {
                                        if (puzzleGrid.getCellValue(j, col) == -1) {
                                            puzzleGrid.setCellFillState(j, col);
                                            msg.sumEqualsLineLength(false, j, col, pointer);

                                            return;
                                        } else if (puzzleGrid.getCellValue(j, col) == 1) {
                                            cluesCopy[pointer] -= 1;
                                        }
                                    }
                                }
                            }

                        }

                        if (lineComplete(puzzleGrid.getCol(col), colClues)) {
                            for (int row = 0; row < size; row++) {
                                if (puzzleGrid.getCellValue(row, col) == -1) {
                                    puzzleGrid.setCellBlankState(row, col);
                                    msg.multiClueAllFilledIn(row, col, false, false);
                                    return;
                                }
                            }
                        }
                        if (puzzleGrid.getNumberFillState(false, 0, col) == (size - sumClues(colClues))) {
                            for (int row = 0; row < size; row++) {
                                if (puzzleGrid.getCellValue(row, col) == -1) {
                                    puzzleGrid.setCellFillState(row, col);
                                    msg.multiClueAllFilledIn(row, col, true, false);
                                    return;
                                }
                            }
                        }
                        if (puzzleGrid.getCellValue(0, col) == 0) {
                            int numberOfBlanks = puzzleGrid.getNumberFillState(false, 0, col);
                            int firstRun = 0;
                            int secondRun = 0;
                            int cell = 0;
                            while (puzzleGrid.getCellValue(cell, col) == 0) {
                                firstRun += 1;
                                cell += 1;
                            }
                            if (numberOfBlanks != firstRun) {
                                cell = size - 1;
                                while (puzzleGrid.getCellValue(cell, col) == 0) {
                                    secondRun += 1;
                                    cell -= 1;
                                }
                            }
                            if ((numberOfBlanks == (firstRun + secondRun)) && ((size - numberOfBlanks) == (sumClues(colClues) + colClues.length - 1))) {
                                int index = 0;
                                int run = 0;
                                for (int row = firstRun; row < size - secondRun; row++) {
                                    if (puzzleGrid.getCellValue(row, col) == 1) {
                                        run += 1;
                                    }
                                    else if (puzzleGrid.getCellValue(row, col) == 0) {
                                        run = 0;
                                        index += 1;
                                    }
                                    else {
                                        if (run == colClues[index]) {
                                            run = 0;
                                            index += 1;
                                            puzzleGrid.setCellBlankState(row, col);
                                            msg.multiClueRemainingLineLengthEqualsClueSum(row, col, 0, false, size - numberOfBlanks);
                                            return;
                                        }
                                        else {
                                            run += 1;
                                            puzzleGrid.setCellFillState(row, col);
                                            msg.multiClueRemainingLineLengthEqualsClueSum(row, col, 1, false, size - numberOfBlanks);
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                        if (puzzleGrid.getCellValue(0, col) == 1) {
                            int run = 0;
                            int cell = 0;
                            while (puzzleGrid.getCellValue(cell, col) == 1) {
                                run += 1;
                                cell += 1;
                            }
                            if (run == colClues[0]) {
                                if (puzzleGrid.getCellValue(run, col) == -1) {
                                    puzzleGrid.setCellBlankState(run, col);
                                    msg.multiClueFirstClueComplete(run, col, false);
                                    return;
                                }
                            }
                        }

                        if (puzzleGrid.getCellValue(size - 1, col) == 1) {
                            int run = 0;
                            int cell = size - 1;
                            while (puzzleGrid.getCellValue(cell, col) == 1) {
                                run += 1;
                                cell -= 1;
                            }
                            if (run == colClues[colClues.length - 1]) {
                                if (puzzleGrid.getCellValue(size - run - 1, col) == -1) {
                                    puzzleGrid.setCellBlankState(size - run - 1, col);
                                    msg.multiClueLastClueComplete(size-run-1, col, false);
                                    return;
                                }
                            }
                        }
                        int firstCellMarked = puzzleGrid.getFirstCellState(false, 1, col, 0);
                        if (firstCellMarked >= 0) {
                            int blankSpace = 0;
                            int cell = 0;
                            while (puzzleGrid.getCellValue(cell, col) != 1) {
                                if (puzzleGrid.getCellValue(cell, col) == -1) {
                                    blankSpace += 1;
                                }
                                cell += 1;
                            }
                            if ((colClues[0] > 1 && blankSpace < colClues[0]) || 
                                    (blankSpace < sumClues(colClues) + colClues.length && blankSpace <= colClues[0])) {
                                int run = 0;
                                cell = firstCellMarked;
                                while (puzzleGrid.getCellValue(cell, col) == 1) {
                                    run += 1;
                                    cell += 1;
                                }
                                if (run == colClues[0]) {
                                    for (int row = 0; row < firstCellMarked; row++) {
                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                            puzzleGrid.setCellBlankState(row, col);
                                            msg.multiClueFirstClueComplete(row, col, false);
                                            return;
                                        }
                                    }
                                    if (puzzleGrid.getCellValue(firstCellMarked + run, col) == -1) {
                                        puzzleGrid.setCellBlankState(firstCellMarked + run, col);
                                        msg.multiClueFirstClueComplete(firstCellMarked+run, col, false);
                                        return;
                                    }
                                }
                            }
                        }
                        int lastCellMarked = puzzleGrid.getLastCellState(false, 1, col, size - 1);
                        if (lastCellMarked > 0) {
                            int blankSpace = 0;
                            int cell = size - 1;
                            while (puzzleGrid.getCellValue(cell, col) != 1) {
                                if (puzzleGrid.getCellValue(cell, col) == -1) {
                                    blankSpace += 1;
                                }
                                cell -= 1;
                            }
                            if ((colClues[colClues.length - 1] > 1 && blankSpace < colClues[colClues.length - 1]) || (blankSpace <= sumClues(colClues) + colClues.length && blankSpace <= colClues[colClues.length - 1])) {
                                int run = 0;
                                cell = lastCellMarked;
                                while (puzzleGrid.getCellValue(cell, col) == 1) {
                                    run += 1;
                                    cell -= 1;
                                }
                                if (run == colClues[colClues.length - 1]) {
                                    for (int row = lastCellMarked + 1; row < size; row++) {
                                        if (puzzleGrid.getCellValue(row, col) == -1) {
                                            puzzleGrid.setCellBlankState(row, col);
                                            msg.multiClueLastClueComplete(row, col, false);
                                            return;
                                        }
                                    }
                                    if (puzzleGrid.getCellValue(lastCellMarked - run, col) == -1) {
                                        puzzleGrid.setCellBlankState(lastCellMarked - run, col);
                                        msg.multiClueLastClueComplete(lastCellMarked-run, col, false);
                                        return;
                                    }
                                }
                            }
                        }
                    }
                        
          //EDGE RELATED CLUES Sorry its long  
          //Edges Filling
                if (colClues[0] != 1){
                Boolean foundGivenCell = false;
                int pointerPush = 0;
	                while (true){
	                	if (puzzleGrid.getCellValue(pointerPush, col)== 0){
	                		pointerPush = pointerPush+1;
	                	}
	                	else{break;	}
	                	
	                	if(pointerPush==size-1){break;}	
	                }
                for(int row = pointerPush; row < colClues[0]+pointerPush; row++){
                	if (foundGivenCell && puzzleGrid.getCellValue(row, col) == -1){
                		puzzleGrid.setCellFillState(row, col);
                		msg.firstColClueEdgeMessage(row, col, pointerPush, colClues[0]);
                		return;
                	}
                	else if (puzzleGrid.getCellValue(row, col) == 1){
                		foundGivenCell = true;
                	}
                	if (row == size-1){
                		break;
                	}
                }
                }
                
                if (colClues[colClues.length-1] != 1){
                Boolean foundGivenCell = false;
                int pointerPush = size-1;
	                while (true){
	                	if (puzzleGrid.getCellValue(pointerPush, col)== 0){
	                		pointerPush = pointerPush-1;
	                	}
	                	else{
	                		break;}
	                	if(pointerPush==0){break;}	                	
	                }
                foundGivenCell = false;
                for(int row = pointerPush; row > (pointerPush - colClues[colClues.length-1]); row--){
                	if (foundGivenCell && puzzleGrid.getCellValue(row, col) == -1){
                		puzzleGrid.setCellFillState(row, col);
                		msg.LastColClueEdgeMessage(row, col, size-1 -pointerPush, colClues[colClues.length-1]);
                		return;
                	}
                	else if (puzzleGrid.getCellValue(row, col) == 1){
                		foundGivenCell = true;
                	}
                	if (row==0){
                		break;
                	}
                }
                }
              //Edges Blanking
                if (colClues[0] != 1){
                  Boolean foundGivenCell = false;
	              for(int row = colClues[0]-1; row > -1; row--){
	            	  if (foundGivenCell && puzzleGrid.getCellValue(row, col) == -1){
	                		puzzleGrid.setCellBlankState(row, col);
	                		msg.firstColClueEdgeBlankMessage(row, col, colClues[0]);
	                		return;
	                	}
	                	else if (puzzleGrid.getCellValue(row, col) == 0){
	                		foundGivenCell = true;
	                	}
	              	}
	              }
                if (colClues[colClues.length-1] != 1){
	              Boolean foundGivenCell = false;
	              for(int row = ((size) - colClues[colClues.length-1]); row < size; row++){
	            	  if (foundGivenCell && puzzleGrid.getCellValue(row, col) == -1){
	                		puzzleGrid.setCellBlankState(row, col);
	                		msg.LastColClueEdgeBlankMessage(row, col, colClues[colClues.length-1]);
	                		return;
	                	}
	                	else if (puzzleGrid.getCellValue(row, col) == 0){
	                		foundGivenCell = true;
	                	}
	              }
                }
                
         	//Overlap first clue Possibles
            if (colClues[0] != 1 && colClues[0] !=0){
            	int end =((size-1)-(sumClues(colClues))+(colClues[0])-(colClues.length-1));
            	int start = end-colClues[0]+1;
            	
            	
            	for(int overlapPointer = 0; overlapPointer < colClues[0]; overlapPointer++){
            		if(overlapPointer <=end && overlapPointer>=start){
            			if (puzzleGrid.getCellValue(overlapPointer, col)== -1){
            				puzzleGrid.setCellFillState(overlapPointer, col);
            				msg.overlapFirstColClueMC(overlapPointer, col);
                    		return;
            			}
            		}
            	}
            }
            //Overlap last clue Possibles
            if (colClues[colClues.length-1] != 1 && colClues[0] !=0){
            	int start = (sumClues(colClues)-colClues[colClues.length-1])+colClues.length-1;
            	int end = start + colClues[colClues.length-1]-1;
            	for(int overlapPointer = ((size-1)- colClues[colClues.length-1])+1; overlapPointer < size; overlapPointer++){
            		if(overlapPointer <=end && overlapPointer>=start){
            			if (puzzleGrid.getCellValue(overlapPointer, col)== -1){
            				puzzleGrid.setCellFillState(overlapPointer, col);
                    		msg.overlapLastColClueMC(overlapPointer, col);
                    		return;
            			}
            		}
            	}
            }
            ////////
      	  //Process the line Forward
      	  ///////
                while(true){
              	  int row = 0;
              	  int cluePointer = 0;
              	  int clueValueRemaining = colClues[cluePointer];
              	  
              	  while(row<size -1){
              		  
              		  if(puzzleGrid.getCellValue(row, col) == 1){
              			  if (clueValueRemaining == 1){
              				  if (puzzleGrid.getCellValue(row+1, col) == -1){
              				   puzzleGrid.setCellBlankState(row+1, col);
              				   msg.processFromFrontColBlank(row, col, cluePointer, colClues[cluePointer]);
              				   return;}
              			  }
              			  else{
              				  while(clueValueRemaining!=0 && row != size -1){
              					  clueValueRemaining = clueValueRemaining-1;
              					  
              					  if (puzzleGrid.getCellValue(row+1, col) == -1){
              						  //Value remaining fill
              						  if (clueValueRemaining >0 ){
              							  puzzleGrid.setCellFillState(row+1, col);
              	        				  msg.processFromFrontColFill(row, col, cluePointer, colClues[cluePointer]);
              	        				  return;
              						  }
              						//Blank outspace space blank
              						  else if (clueValueRemaining == 0){
              							  puzzleGrid.setCellBlankState(row+1, col);
              							  msg.processFromFrontColBlank(row, col, cluePointer, colClues[cluePointer]);
              	        				  return;
              						  }
              						  
              						  
              					  }
              					  
              					row = row +1;
              				  }
              			  }
              			  cluePointer = cluePointer +1;
              			  if(cluePointer == colClues.length){
              				  break;
              			  }
              			  clueValueRemaining = colClues[cluePointer];
              			  
              		  }
              		  
              		  if(puzzleGrid.getCellValue(row, col) == -1){
              			  break;
              		  }

              		row = row +1;
              	  }
              	  break;
                }           
  	  ////////
  	  //Process the line Backwards
  	  ///////
            while(true){
          	  int row = size -1;
          	  int cluePointer = colClues.length-1;
          	  int clueValueRemaining = colClues[cluePointer];
          	  
          	  while(row>0){
          		  
          		  if(puzzleGrid.getCellValue(row, col) == 1){
          			  if (clueValueRemaining == 1){
          				  if (puzzleGrid.getCellValue(row-1, col) == -1){
          				   puzzleGrid.setCellBlankState(row-1, col);
          				   msg.processFromBackColBlank(row, col, cluePointer, colClues.length-1, colClues[cluePointer]);
          				   return;}
          			  }
          			  else{
          				  while(clueValueRemaining!=0 && row != 0){
          					  clueValueRemaining = clueValueRemaining-1;
          					  
          					  if (puzzleGrid.getCellValue(row-1, col) == -1){
          						  //Value remaining fill
          						  if (clueValueRemaining >0 ){
          							  puzzleGrid.setCellFillState(row-1, col);
          	        				  msg.processFromBackColFill(row, col, cluePointer, colClues.length-1, colClues[cluePointer]);
          	        				  return;
          						  }
          						  else if (clueValueRemaining == 0){
          							  puzzleGrid.setCellBlankState(row-1, col);
          	        				  msg.processFromBackColBlank(row, col, cluePointer, colClues.length-1, colClues[cluePointer]);
          	        				  return;
          						  }
          						  
          						  //Blank outspace space blank
          					  }
          					  
          					row = row -1;
          				  }
          			  }
          			  cluePointer = cluePointer -1;
          			  if(cluePointer == -1){
          				  break;
          			  }
          			  clueValueRemaining = colClues[cluePointer];
          			  
          		  }
          		  
          		  if(puzzleGrid.getCellValue(row, col) == -1){
          			  break;
          		  }

          		row = row -1;
          	  }
          	  break;
            }
                
                
      ////////
  	  //Blank out small gaps
  	  ///////
  	       if (puzzleGrid.getMinNumClue(colClues) != 1){       
  	    	   int minClue = puzzleGrid.getMinNumClue(colClues);
  	    	   int row = 0;
  	    	   int start=0;
  	    	   int blankGapRange = 0;
  	    	   
  	    	   //Start position
  	    	   while(row < size){
  	    	   
             		if (puzzleGrid.getCellValue(row, col)== -1){
             			start = row;
             			while(puzzleGrid.getCellValue(row, col)== -1){
             				blankGapRange = blankGapRange +1;
             				row = row +1;
             				if (row >= size){
                     			break;}
             				}
             			row = row -1;	
             			}
                 	
             		if (blankGapRange > 0){
             			if (blankGapRange < minClue){
             				if (start == 0){
             					
             				}
             				else if (puzzleGrid.getCellValue(start-1, col)== 0){
             					if(start + blankGapRange == size){
             						puzzleGrid.setCellBlankState(start, col);
             						msg.smallGapCol(row, col, minClue);
             						return;
             					}
             					else if (puzzleGrid.getCellValue(start+blankGapRange, col)== 0){
             						puzzleGrid.setCellBlankState(start, col);
             						msg.smallGapCol(row, col, minClue);
             						return;
             					}
             					
             					
             				}
             			}
             			start = row+1;
             			blankGapRange = 0;
             		}
             		
             		row = row + 1;
             		
  	    	   	}//While
  	    	   }
                //END OF EDGE CLUES
                
            }}
            runningSolver=false;
        }

    
    
        // * * * * * * * * * * * * * * * //
    //			Sum Clues Method	 //
    // * * * * * * * * * * * * * * * //
    private int sumClues(int[] clues) {
        int sum = 0;
        for (int i = 0; i < clues.length; i++) {
            sum += clues[i];
        }
        return sum;
    }

        // * * * * * * * * * * * * * * * //
    //		Clue Match Method		 //
    // * * * * * * * * * * * * * * * //
    // 
    private boolean clueMatched(int[] line, int clue) {
        int fillCount = 0;
        for (int i = 0; i < size; i++) {
            if (line[i] == 1) {
                fillCount++;
            } else if (clue == fillCount) {
                return true;
            } else {
                fillCount = 0;
            }
        }
        return false;
    }

        // * * * * * * * * * * * * * * * //
    //		Line Complete Method	 //
    // * * * * * * * * * * * * * * * //
    // Returns true if completely satisfied and false if partially completed
    private boolean lineComplete(int[] line, int[] clues) {
        int index = 0;
        int cluesMatched = 0;
        int fillCount = 0;
        for (int i = 0; i < size; i++) {
            if (line[i] == 1) {
                fillCount++;
            } else if (fillCount == clues[index]) {
                cluesMatched++;
                index++;
                fillCount = 0;
                if (index > clues.length - 1) {
                    index = clues.length - 1;
                }
            }
        }
        if (fillCount == clues[index]) {
            cluesMatched++;
        }
        if (cluesMatched == clues.length) {
            return true;
        } else {
            return false;
        }
    }

        // * * * * * * * * * * * * * * * //
    //		Line Solver Method		 //
    // * * * * * * * * * * * * * * * //
    private int LineSolver(int[] line, int[] clues, int startIndex, int space) {

        // make two copies of the original line,
        int[] lineCopyOne = new int[size];
        int[] lineCopyTwo = new int[size];
        int cluesCounter1 = clues[0];
        int cluesCounter2 = clues[0];
        int endIndex = startIndex + space - 1;

        for (int i = 0; i < size; i++) {
            lineCopyOne[i] = line[i];
            lineCopyTwo[i] = line[i];
        }

        for (int i = startIndex; i < space; i++) {
            if (cluesCounter1 != 0) {
                lineCopyOne[i] = 1;
                cluesCounter1 -= 1;
            }
        }
        for (int j = endIndex; j >= startIndex; j--) {

            if (cluesCounter2 != 0) {
                lineCopyTwo[j] = 1;
                cluesCounter2 -= 1;
            }
        }

        for (int i = startIndex; i < space; i++) {
            if ((lineCopyOne[i] == 1) && (lineCopyTwo[i] == 1)) {   
                if (line[i] != 1) {
                    return i;
                }

            }
        }
        return -1;  
    }

///////////////////////////////////////////////////////////////////////////////////////
/////////////////////    RUN SOlVER AS LONG AS POSSIBLE    /////////////////////////////
    public void runSolverAsLongAsPossible() {
        runningSolver = true;
        while (runningSolver) {
            runSolver();
        }
    }

////////////////////////////////////////////////////////////////////////////////////////
///////////////////////      ERROR DETECTION        /////////////////////////////////////
    public boolean checkForErrorsBeforeRunning() {
        return this.errorD.checkForErrorsBeforeRunning();
    }

    public boolean ErrorDetection() {
        return this.errorD.ErrDetection();
    }
}